
#include <stdio.h>
#include <windows.h>
#include "imgUrUploader.h"
#include "curl.h"
#include "tinyxml.h"
#include "polarssl\_base64.h"

#define RAISE_ERR(e) { ret = (e); goto ERRL; }

//
// function parses XML response from imgur server
//
int parseResponse(char *strRsp, char *imgUri, char *delUri)
{
 int ret = 0;

 TiXmlDocument doc("");
 TiXmlElement *pXmlE;
 TiXmlNode *pXmlN, *pXmlN2;

 char *p, *p2;

 doc.Parse(strRsp);

 if(doc.Error())
  RAISE_ERR(IUE_XML_DOC_ERROR)
 else
  pXmlE = doc.RootElement();

 p = (char*)pXmlE->Attribute("stat");

 // upload OK
 if(strcmp(p, "ok") == 0)
 {
  pXmlN = pXmlE->FirstChild();
  while (pXmlN)
  {
   p = (char*)pXmlN->Value();
   pXmlN2 = pXmlN->FirstChild();
   p2 = (char*)pXmlN2->Value();
   if(strcmp(p, "delete_page") == 0)
   {
    strcpy(delUri, p2);
   }
   else if(strcmp(p, "original_image") == 0)
   {
    strcpy(imgUri, p2);
   }

   pXmlN = pXmlN->NextSibling();
  }
 }
 // upload fail
 else if(strcmp(p, "fail") == 0)
 {
  pXmlN = pXmlE->FirstChild();
  while (pXmlN)
  {
   p = (char*)pXmlN->Value();
   pXmlN2 = pXmlN->FirstChild();
   p2 = (char*)pXmlN2->Value();
   if(strcmp(p, "error_code") == 0)
   {
    strcpy(delUri, p2);
    ret = atol(p2);
   }
   else if(strcmp(p, "error_msg") == 0)
   {
    strcpy(imgUri, p2);
   }

   pXmlN = pXmlN->NextSibling();
  }
  // TODO: parse the imgur error here 
  // (maybe create internal buffer and set error message)
 }
 else
  RAISE_ERR(IUE_UNKNOWN_RESPONSE_STATUS);

ERRL:
 return ret;
}

char *gPtr;
// function for receiving data from cURL
// sets data on gPtr, it has to be freed!
size_t writeFunction(void *ptr, size_t size, size_t nmemb, void *stream)
{
 size_t dataLen = size * nmemb;
 if(gPtr = (char*) malloc(dataLen + size))
  memset(gPtr, 0, dataLen + size);
 else
  return 0;

 memcpy(gPtr, ptr, dataLen);
 return size * nmemb;
}

//
// exported function for posting an image
//
int imgurPostImage(unsigned long ulMethod, const char *uri, char *iUri, char *dUri)
{
 CURL *curl;
 CURLcode res;
 CURLFORMcode fres;

 /*
 MessageBox(NULL, uri, "img uploader", 0);
 */

 struct curl_httppost* post = NULL;
 struct curl_httppost* last = NULL;

 int ret;

 FILE * imgFile = NULL;
 unsigned char *rawImg = NULL, *encImg = NULL;
 int rawImgL, encImgL = 0;

 curl_formadd(&post, &last, CURLFORM_COPYNAME, "key",
  CURLFORM_COPYCONTENTS, "5956d05dbbfdf5b4974160e7baa3b09b", CURLFORM_END);

 if(ulMethod == IU_METHOD_HTTP)
 {
  fres = curl_formadd(&post, &last, CURLFORM_COPYNAME, "image", CURLFORM_COPYCONTENTS, uri, CURLFORM_END);
 }
 else if(ulMethod == IU_METHOD_FILE)
 {
  // TODO: misto file uploadu nacist soubor jako base64 a poslat jako parametr
  // fres = curl_formadd(&post, &last, CURLFORM_COPYNAME, "image", CURLFORM_FILE, uri, CURLFORM_END);
  if(!(imgFile = fopen(uri, "rb")))
   RAISE_ERR(IUE_FILE_NOT_FOUND);

  fseek(imgFile, 0, SEEK_END);
  rawImgL = ftell(imgFile);
  fseek(imgFile, 0, SEEK_SET);
  
  if(!(rawImg = (unsigned char *)malloc(rawImgL)))
   RAISE_ERR(IUE_MALLOC_FAILED)
   
  if(fread(rawImg, 1, rawImgL, imgFile) != (size_t) rawImgL)
   RAISE_ERR(IUE_FILE_READ_ERR)

  ret = base64_encode(NULL, &encImgL, rawImg, rawImgL);
  if(!(encImg = (unsigned char *)malloc(encImgL)))
   RAISE_ERR(IUE_MALLOC_FAILED)

  ret = base64_encode(encImg, &encImgL, rawImg, rawImgL);

  fres = curl_formadd(&post, &last, CURLFORM_COPYNAME, "image", CURLFORM_COPYCONTENTS, encImg, CURLFORM_END);
 }
 else
  RAISE_ERR(IUE_FILE_NOT_FOUND);

 if(fres)
  RAISE_ERR(IUE_CURL_FORM_ADD_ERROR);

 curl = curl_easy_init();
 if(curl) {
  // write callback
  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeFunction);

  curl_easy_setopt(curl, CURLOPT_URL, "http://imgur.com/api/upload.xml");
  curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);

  res = curl_easy_perform(curl);

  if(!res)
  {
   ret = parseResponse(gPtr, iUri, dUri);
   free(gPtr);
  }
  else
  {
   ret = IUE_CURL_PERFORM_ERROR;
   // sprintf(lasterr, "%s", curl_easy_strerror(res));
  }

  /* always cleanup */
  curl_easy_cleanup(curl);
 }
 else
  ret = IUE_CURL_NOT_INITIALIZED;//puts("curl_easy_init(): failed!");

ERRL:
 if(rawImg) free(rawImg);
 if(encImg) free(encImg);
 if(imgFile) fclose(imgFile);
 return ret;
}
